/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：呼叫中心-业务逻辑层-权限控制管理-接口实现
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taiping.cc.authorize.service.impl;

import com.taiping.cc.authorize.app.properties.AuthorizeBizProperty;
import com.taiping.cc.authorize.base.BaseService;
import com.taiping.cc.authorize.converter.AuthLoginBOConverter;
import com.taiping.cc.authorize.converter.AuthLoginDOConverter;
import com.taiping.cc.authorize.dataobject.AuthLoginDO;
import com.taiping.cc.authorize.pojo.dto.AuthLoginDTO;
import com.taiping.cc.authorize.service.AccountService;
import com.taiping.dlt.pojo.bo.AuthLoginBO;
import com.taipingframework.boot.web.response.result.ApiResult;
import com.taipingframework.boot.web.response.status.ApiStatusEnum;
import com.taipingframework.boot.web.security.SecretHandler;
import com.taipingframework.utility.exception.ServiceException;
import com.taipingframework.utility.exception.SystemInterrupterException;
import com.taipingframework.utility.thread.wrapper.BenchmarksFuture;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Slf4j
@Service
@RequestMapping("/service/account")
@RequiredArgsConstructor
public class AccountServiceImpl extends BaseService implements AccountService {

    private final AuthorizeBizProperty authorizeBizProperty;

    /**
     * 禁用账户/(逻辑)删除账户
     */
    @Override
    public ApiResult<Boolean> disableAccount(AuthLoginBO authLogin) throws ServiceException {
        log.debug("动态感知业务配置的变更：{}", authorizeBizProperty.toString());
        try {
            return BenchmarksFuture.completedFuture(
                    authorizeCacheService.queryWithLoginName(authLogin.getAccountCode())
            ).thenComposeAsync(authLoginDOList -> {
                String loginName = authLoginDOList.stream()
                        .map(AuthLoginDO::getLoginName)
                        .findFirst()
                        .orElse(StringUtils.EMPTY);
                if (StringUtils.isEmpty(loginName)) {
                    return BenchmarksFuture.completedFuture(false);
                }
                return BenchmarksFuture.completedFuture(authorizeCacheService.disableAccount(loginName));
            }).thenApplyAsync(flag -> ApiResult.<Boolean>build()
                    .setStatus(ApiStatusEnum.SUCCESS)
                    .setResult(flag)
            ).exceptionally(throwable -> {
                throw new ServiceException(throwable.getCause());
            }).join();
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    /**
     * 接收用户登录认证数据
     */
    @Override
    public ApiResult<Boolean> receive(AuthLoginDTO authLoginDTO) throws ServiceException {
        log.debug("动态感知业务配置的变更：{}", authorizeBizProperty.toString());
        try {
            return BenchmarksFuture.supplyAsync(() -> {
                List<AuthLoginBO> authLoginBOList = authLoginDTO.getAuthLoginBOList();
                return AuthLoginDOConverter.convert(authLoginBOList);
            }).thenCompose(
                    // 注意，此处在向数据库插入数据时，应该考虑实际的业务规则并加以限制
                    authLoginDAO::insertAuthLoginDataBatch
            ).thenApplyAsync(flag -> ApiResult.<Boolean>build()
                    .setStatus(ApiStatusEnum.SUCCESS)
                    .setResult(flag)
            ).exceptionally(throwable -> {
                throw new ServiceException(throwable.getCause());
            }).join();
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public ApiResult<AuthLoginBO> valid(AuthLoginBO authLogin) throws ServiceException {
        log.debug("动态感知业务配置的变更：{}", authorizeBizProperty.toString());
        try {
            return BenchmarksFuture.completedFuture(
                    authorizeCacheService.queryWithLoginName(authLogin.getAccountCode())
            ).thenApplyAsync(authLoginList -> {
                List<AuthLoginBO> authLoginBOList = AuthLoginBOConverter.convert(authLoginList);
                if (authLoginBOList.size() <= 0) {
                    log.error(ApiStatusEnum.ERR_A0201.getMessage() + "：{}", authLogin.getLoginName());
                    throw new SystemInterrupterException(ApiStatusEnum.ERR_A0201);
                }
                AuthLoginBO authLoginBO = authLoginBOList.get(0);
                String secPwd = SecretHandler.encryptForChar(authLogin.getLoginPassword());
                if (!StringUtils.equals(secPwd, authLoginBO.getLoginPassword())) {
                    log.error(ApiStatusEnum.ERR_A0210 + "，登录名：{}，密码：{}", authLogin.getLoginName(), authLogin.getLoginPassword());
                    throw new SystemInterrupterException(ApiStatusEnum.ERR_A0210);
                }

                // FIXME：用户登录成功之后，并非马上返回，此时还需要读取用户的角色信息
                return ApiResult.<AuthLoginBO>build()
                        .setStatus(ApiStatusEnum.SUCCESS)
                        .setResult(authLoginBO);
            }).exceptionally(throwable -> {
                throw new ServiceException(throwable.getCause());
            }).join();
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

}
